package com.jumi.microservice.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jumi.microservice.common.base.BaseController;
import com.jumi.microservice.common.base.dto.BasePageResponse;
import com.jumi.microservice.common.base.dto.ResponseResult;
import com.jumi.microservice.common.constant.CloneDirection;
import com.jumi.microservice.common.constant.RequestConstant;
import com.jumi.microservice.common.constant.ResultEnum;
import com.jumi.microservice.common.core.aspect.WebLog;
import com.jumi.microservice.common.redis.RedisCache;
import com.jumi.microservice.common.utils.ObjectUtils;
import com.jumi.microservice.common.utils.ResultGenerator;
import com.jumi.microservice.constant.*;
import com.jumi.microservice.domain.*;
import com.jumi.microservice.domain.GoodsSkuStockDTO;
import com.jumi.microservice.domain.GoodsSkuStockVO;
import com.jumi.microservice.domain.SkuSupplyAddVO;
import com.jumi.microservice.material.domain.JmGoodsTax;
import com.jumi.microservice.material.dto.JmGoodsResponse;
import com.jumi.microservice.material.dto.supplier.JmSupplierResponse;
import com.jumi.microservice.material.service.IGoodTaxService;
import com.jumi.microservice.material.service.IJmGoodsService;
import com.jumi.microservice.service.*;
import com.jumi.microservice.stock.api.IJmStockApi;
import com.jumi.microservice.stock.api.dto.CommodityMaterialStockDTO;
import com.jumi.microservice.stock.dto.commodity.CommodityApplyDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.List;


/**
 * 商品管理controller组件
 *
 * @author Administrator
 */
@RestController
@Api(tags = "商品管理相关接口")
@RequestMapping("/commodity/goods")
public class GoodsController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(GoodsController.class);

    /**
     * 商品spu管理service组件
     */
    @Autowired
    private GoodsService goodsService;

    /**
     * 库存管理service组件
     */
    @DubboReference
    private GoodsInventoryApi goodsInventoryApi;

    /**
     * 日志管理service组件
     */
    @Autowired
    private LogService logService;

    /**
     * 供应链物料管理service组件
     */
    @DubboReference
    private IJmGoodsService supplyService;

    /**
     * 供应链厂商管理service组件
     */
    @Autowired
    private SupplierService supplierService;

    /**
     * 商品sku管理service组件
     */
    @Autowired
    private GoodsSkuService goodsSkuService;

    /**
     * 供应链计算库存
     */
    @DubboReference
    private IJmStockApi supplyStockService;

    /**
     * 商品分类管理service组件接口
     */
    @Autowired
    private CategoryService categoryService;

    @DubboReference
    private IGoodTaxService goodsTaxService;

    @Autowired
    private RedisCache redisCache;

    @GetMapping("/test")
    public ResponseResult<Boolean> listGoods(@RequestParam("skuId") Long skuId) {
        logger.info("商品管理-listGoods查询-start:" + skuId);
        List<Long> goodsSkuIds = new ArrayList<>();
        goodsSkuIds.add(skuId);
        List<GoodsSpuInventoryDTO> goodsSpuInventories = goodsInventoryApi.goodsInventoryBySkuIds(goodsSkuIds);
        logger.info("商品管理-listGoods查询-end:" + goodsSpuInventories.size());
        return ResultGenerator.genSuccessResult(Boolean.TRUE);
    }

    /**
     * 商品分页查询
     *
     * @param goodsQuery 商品查询条件
     * @return 商品展现VO值对象集合
     */
    @ApiOperation(value = "商品管理-商品列表分页查询", notes = "商品管理-商品列表分页查询")
    @GetMapping("/list")
    public BasePageResponse<List<GoodsShowVO>> listGoodsByPage(GoodsQuery goodsQuery) {
        logger.info("商品管理-商品列表分页查询:" + goodsQuery.toString());
        List<GoodsShowVO> goodsShows = convertGoodsShowDtoList2VoList(goodsService.listGoodsByPage(goodsQuery));

        List<Long> goodsSkuIds = new ArrayList<>();
        Map<Long, Integer> skuAlertStorageMap = new HashMap<>();
        for (GoodsShowVO goodsShow : goodsShows) {
            Long spuId = goodsShow.getGoodsId();
            List<Long> skuIds = goodsService.getSkuIdListBySpuId(spuId);
            goodsSkuIds.addAll(skuIds);

            List<GoodsSkuDTO> goodsSkus = goodsSkuService.listGoodsSku(spuId);
            for (GoodsSkuDTO sku : goodsSkus) {
                skuAlertStorageMap.put(sku.getId(), sku.getAlertStorage());
            }
        }
        if (goodsSkuIds.size() > NumberConstant.NUMBER_ZERO.intValue()) {
            //调用库存服务查询库存
            List<GoodsSpuInventoryDTO> goodsSpuInventories = goodsInventoryApi.goodsInventoryBySkuIds(goodsSkuIds);
            Map<Long, List<GoodsSpuInventoryDTO>> spuInventoryMap = new HashMap<>(goodsShows.size());
            for (GoodsSpuInventoryDTO goodsSpuInventory : goodsSpuInventories) {
                if (!spuInventoryMap.containsKey(goodsSpuInventory.getSpuId())) {
                    List<GoodsSpuInventoryDTO> goodsSpuInventoryDTOList = new ArrayList<>();
                    goodsSpuInventoryDTOList.add(goodsSpuInventory);
                    spuInventoryMap.put(goodsSpuInventory.getSpuId(), goodsSpuInventoryDTOList);
                } else {
                    spuInventoryMap.get(goodsSpuInventory.getSpuId()).add(goodsSpuInventory);
                }
            }
            for (GoodsShowVO goodsShow : goodsShows) {
                int storage = NumberConstant.NUMBER_ZERO.intValue();
                if (spuInventoryMap.containsKey(goodsShow.getGoodsId())) {
                    List<GoodsSpuInventoryDTO> goodsSpuInventoryDtoList = spuInventoryMap.get(goodsShow.getGoodsId());

                    for (GoodsSpuInventoryDTO goodsSpuInventory : goodsSpuInventoryDtoList) {
                        int stock = goodsSpuInventory.getStockQuantity() + goodsSpuInventory.getPreStorage();

                        if (stock < skuAlertStorageMap.get(goodsSpuInventory.getSkuId())) {
                            goodsShow.setIsWarning(InventoryStatus.WARNING);
                        }
                        storage += stock;
                    }
                }
                goodsShow.setGoodsPresetStorage(storage);
            }
        }

        if (goodsQuery.getInventoryState() != null) {
            if (goodsQuery.getInventoryState().equals(InventoryStatus.WARNING)) {
                List<GoodsShowVO> goodsShowVOCollect = goodsShows.stream()
                        .filter(goodsShowVo -> goodsShowVo.getIsWarning() != null)
                        .filter(goodsShowVo -> goodsShowVo.getIsWarning().equals(InventoryStatus.WARNING)).collect(Collectors.toList());

                return ResultGenerator.genSuccessResultPage(
                        goodsShowVOCollect.stream()
                                .skip(goodsQuery.getPageSize() * (goodsQuery.getPageNum() - NumberConstant.NUMBER_ONE.intValue()))
                                .limit(goodsQuery.getPageSize()).collect(Collectors.toList())
                        , Long.valueOf(goodsShowVOCollect.size()));
            }
        }
        return ResultGenerator.genSuccessResultPage(
                goodsShows.stream()
                        .skip(goodsQuery.getPageSize() * (goodsQuery.getPageNum() - NumberConstant.NUMBER_ONE.intValue()))
                        .limit(goodsQuery.getPageSize()).collect(Collectors.toList())
                , Long.valueOf(goodsShows.size()));
    }

    /**
     * 新增商品
     *
     * @param goods   商品VO值对象
     * @param request request
     * @return 返回结果成功与否
     */
    @ApiOperation(value = "商品管理-商品列表-添加商品", notes = "商品管理-商品列表-添加商品")
    @PostMapping("/add")
    @WebLog(description = "新增商品")
    public ResponseResult<Boolean> addGoods(@Validated @RequestBody GoodsVO goods, HttpServletRequest request) {
        logger.info("获取到添加商品参数:{}", JSONObject.toJSONString(goods));
        GoodsDTO goodsDTO = convertGoodsVo2Dto(goods);
        GoodsTaxDTO goodsTaxDto = new GoodsTaxDTO();
        goodsTaxDto.setSpuId(goods.getGoodsTax().getSpuId());
        goodsTaxDto.setTaxCode(goods.getGoodsTax().getTaxCode());
        goodsTaxDto.setTaxRate(goods.getGoodsTax().getTaxRate());
        goodsDTO.setGoodsTax(goodsTaxDto);
        logger.info("获取到添加商品封装后参数:{}", JSONObject.toJSONString(goods));
        List<GoodsSkuDTO> goodsSkus = goodsService.addGoods(goodsDTO, request);
        if (goods.getGoodsType().equals(GoodsType.THIRD_PARTY)) {
            List<GoodsSkuStockDTO> goodsSkuStocks = new ArrayList<>();
            for (GoodsSkuDTO goodsSku : goodsSkus) {
                GoodsSkuStockDTO goodsSkuStock = new GoodsSkuStockDTO();
                goodsSkuStock.setSkuId(goodsSku.getId());
                goodsSkuStock.setSkuCode(goodsSku.getSkuCode());
                goodsSkuStock.setId(goodsSku.getGoodsId());
                goodsSkuStock.setGoodsType(goodsSku.getGoodsType());
                goodsSkuStock.setStockQuantity(goodsSku.getSaleStockQuantity());
                goodsSkuStocks.add(goodsSkuStock);
            }
            goodsInventoryApi.saveInventory4Third(goodsSkuStocks);
        }
        return ResultGenerator.genSuccessResult(Boolean.TRUE);
    }

    /**
     * 添加商品-选择商品
     *
     * @param goodsName 商品名称
     * @return List<JmGoodsResponse>
     */
    @ApiOperation(value = "商品管理-商品列表-添加商品-选择商品", notes = "商品管理-商品列表-添加商品-选择商品")
    @PostMapping("/list/supply")
    public ResponseResult<List<JmGoodsResponse>> getSkuListByGoodsName(@RequestParam String goodsName) {
        return supplyService.findAllByName(goodsName);
    }

    /**
     * 添加商品-选择税收分类(第三方商品)
     *
     * @return List<JmGoodsTax>
     */
    @ApiOperation(value = "商品管理-商品列表-添加商品-选择税收分类(第三方商品)", notes = "商品管理-商品列表-添加商品-选择税收分类(第三方商品)")
    @GetMapping("/list/tax")
    public ResponseResult<List<JmGoodsTax>> getGoodsTaxList() {
        return goodsTaxService.findAll();
    }

    /**
     * 更新商品
     *
     * @param goods   商品VO值对象
     * @param request request
     * @return 返回结果成功与否
     */
    @ApiOperation(value = "商品管理-商品列表-编辑更新商品", notes = "商品管理-商品列表-编辑更新商品")
    @PutMapping("/update")
    @WebLog(description = "更新商品")
    public ResponseResult<Boolean> updateGoods(@Validated @RequestBody GoodsVO goods, HttpServletRequest request) {
        GoodsDTO goodsDTO = convertGoodsVo2Dto(goods);

        if (Objects.nonNull(goods.getGoodsTax())) {
            GoodsTaxDTO goodsTaxDto = new GoodsTaxDTO();
            goodsTaxDto.setId(goods.getGoodsTax().getId());
            goodsTaxDto.setSpuId(goods.getGoodsTax().getSpuId());
            goodsTaxDto.setTaxCode(goods.getGoodsTax().getTaxCode());
            goodsTaxDto.setTaxRate(goods.getGoodsTax().getTaxRate());
            goodsDTO.setGoodsTax(goodsTaxDto);
        }

        List<GoodsSkuDTO> goodsSkus = goodsService.updateGoods(goodsDTO, request);
        if (goods.getGoodsType().equals(GoodsType.THIRD_PARTY)) {
            List<GoodsSkuStockDTO> goodsSkuStocks = new ArrayList<>();
            for (GoodsSkuDTO goodsSku : goodsSkus) {
                GoodsSkuStockDTO goodsSkuStock = new GoodsSkuStockDTO();
                goodsSkuStock.setSkuId(goodsSku.getId());
                goodsSkuStock.setSkuCode(goodsSku.getSkuCode());
                goodsSkuStock.setId(goodsSku.getGoodsId());
                goodsSkuStock.setGoodsType(goodsSku.getGoodsType());
                goodsSkuStock.setStockQuantity(goodsSku.getSaleStockQuantity());
                goodsSkuStocks.add(goodsSkuStock);
            }
            goodsInventoryApi.saveInventory4Third(goodsSkuStocks);
        }
        if (redisCache.hasObjectByKey(GoodsKeyConstant.GOODS_DETAIL_KEY + goodsDTO.getId())) {
            redisCache.deleteObject(GoodsKeyConstant.GOODS_DETAIL_KEY + goodsDTO.getId());
        }
        return ResultGenerator.genSuccessResult(Boolean.TRUE);
    }

    /**
     * 根据商品spuid查询商品信息
     *
     * @param id 商品spuid
     * @return 商品VO值对象
     */
    @ApiOperation(value = "商品管理-商品列表-查询商品", notes = "商品管理-商品列表-获取指定ID商品数据")
    @ApiImplicitParam(name = "id", value = "ID")
    @GetMapping("/detail/{id}")
    public ResponseResult<GoodsVO> getGoodsById(@PathVariable Long id) {
        GoodsDTO goods = goodsService.getGoodsById(id);
        if (goods.getGoodsType().equals(GoodsType.THIRD_PARTY)) {
            List<GoodsSkuDTO> goodsSkus = goods.getGoodsSkus();
            List<GoodsSkuStockDTO> goodsSkuStocks = new ArrayList<>();
            for (GoodsSkuDTO goodsSku : goodsSkus) {
                GoodsSkuStockDTO goodsSkuStock = new GoodsSkuStockDTO();
                goodsSkuStock.setSkuId(goodsSku.getId());
                goodsSkuStock.setSkuCode(goodsSku.getSkuCode());
                goodsSkuStock.setId(goodsSku.getGoodsId());
                goodsSkuStock.setGoodsType(goodsSku.getGoodsType());
                goodsSkuStocks.add(goodsSkuStock);
            }
            List<GoodsSkuStockDTO> goodsSkuStockDtos = goodsInventoryApi.goodsSkuInventoryList(goodsSkuStocks);
            for (GoodsSkuDTO goodsSku : goodsSkus) {
                for (GoodsSkuStockDTO goodsSkuStockDto : goodsSkuStockDtos) {
                    if (goodsSku.getId().equals(goodsSkuStockDto.getSkuId())) {
                        goodsSku.setSaleStockQuantity(goodsSkuStockDto.getRealStorage());
                    }
                }
            }
        }
        GoodsVO goodsVO = convertGoodsDto2Vo(goods);
        if (Objects.nonNull(goods.getGoodsTax())) {
            GoodsTaxVO goodsTaxVO = new GoodsTaxVO();
            goodsTaxVO.setId(goods.getGoodsTax().getId());
            goodsTaxVO.setSpuId(goods.getGoodsTax().getSpuId());
            goodsTaxVO.setTaxCode(goods.getGoodsTax().getTaxCode());
            goodsTaxVO.setTaxRate(goods.getGoodsTax().getTaxRate());
            goodsVO.setGoodsTax(goodsTaxVO);
        }
        return ResultGenerator.genSuccessResult(goodsVO);
    }

    /**
     * 删除商品(支持批量删除)
     *
     * @param goodsIds 商品id,支持批量删除
     * @return 返回结果成功与否
     */
    @ApiOperation(value = "商品管理-商品列表-删除商品(支持批量删除)", notes = "商品管理-商品列表-删除商品(支持批量删除)")
    @ApiImplicitParam(name = "id", value = "ID")
    @DeleteMapping("/delete/{goodsIds}")
    @WebLog(description = "删除商品")
    public ResponseResult<Boolean> deleteGoods(@PathVariable String goodsIds, HttpServletRequest request) {
        goodsService.deleteGoods(goodsIds, request);
        return ResultGenerator.genSuccessResult(Boolean.TRUE);
    }

    /**
     * 商品上架
     *
     * @param goodsId 商品ID
     * @param request request
     * @return 处理结果
     */
    @ApiOperation(value = "商品管理-商品列表-商品上架", notes = "商品管理-商品列表-商品上架")
    @PutMapping("/putOnShelves/{goodsId}")
    @WebLog(description = "商品上架")
    public ResponseResult<Boolean> putOnShelves(@PathVariable("goodsId") Long goodsId, HttpServletRequest request) {
        Boolean putOnShelves = goodsService.putOnShelves(goodsId, request);

        if (putOnShelves) {
            if (redisCache.hasObjectByKey(GoodsKeyConstant.GOODS_DETAIL_KEY + goodsId)) {
                redisCache.deleteObject(GoodsKeyConstant.GOODS_DETAIL_KEY + goodsId);
            }
        }
        return ResultGenerator.genSuccessResult(putOnShelves);
    }

    /**
     * 商品下架
     *
     * @param goodsId 商品ID
     * @param request request
     * @return 处理结果
     */
    @ApiOperation(value = "商品管理-商品列表-商品下架", notes = "商品管理-商品列表-商品下架")
    @PutMapping("/pullOffShelves/{goodsId}")
    @WebLog(description = "商品下架")
    public ResponseResult<Boolean> pullOffShelves(@PathVariable("goodsId") Long goodsId, HttpServletRequest request) {
        Boolean pullOffShelves = goodsService.pullOffShelves(goodsId, request);

        if (pullOffShelves) {
            if (redisCache.hasObjectByKey(GoodsKeyConstant.GOODS_DETAIL_KEY + goodsId)) {
                redisCache.deleteObject(GoodsKeyConstant.GOODS_DETAIL_KEY + goodsId);
            }
        }

        return ResultGenerator.genSuccessResult(pullOffShelves);
    }

    /**
     * 商品列表页面获取厂家名称下拉列表
     *
     * @return 厂家名称列表
     */
    @ApiOperation(value = "商品列表页面获取厂家名称下拉列表", notes = "商品列表页面获取厂家名称下拉列表")
    @GetMapping("/supplier/list")
    public ResponseResult<List<SupplierVO>> listSupplier() {
        List<SupplierDTO> supplierDtoList = goodsService.listSupplier();
        return ResultGenerator.genSuccessResult(convertSupplierDtoList2VoList(supplierDtoList));
    }

    /**
     * 分页查询供应商地址(跨服调用供应链接口)
     *
     * @return 供应商地址列表
     */
    @ApiOperation(value = "添加商品-退件地址-供应商地址列表", notes = "添加商品-退件地址-供应商地址列表")
    @GetMapping("/supplier/listPage")
    public BasePageResponse<List<JmSupplierResponse>> listSupplierInfoByPage(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam("name") String name) {
        List<JmSupplierResponse> jmSupplierResponseList = supplierService.findAllByName(name).getData();

        return ResultGenerator.genSuccessResultPage(
                jmSupplierResponseList.stream()
                        .skip(pageSize * (pageNum - NumberConstant.NUMBER_ONE.intValue()))
                        .limit(pageSize).collect(Collectors.toList())
                , Long.valueOf(jmSupplierResponseList.size()));
    }

    /**
     * 添加商品-供应商地址下拉列表(跨服调用供应链接口)-第三方商品上架使用
     *
     * @return 供应商地址列表
     */
    @ApiOperation(value = "添加商品-供应商地址下拉列表", notes = "添加商品-供应商地址下拉列表")
    @GetMapping("/supplier/dropList")
    public ResponseResult<List<JmSupplierResponse>> dropListSupplierInfo(@RequestParam("name") String name) {
        return supplierService.findAllByName(name);
    }

    /**
     * 操作日志分页查询
     *
     * @param operateLogQuery 账号查询条件
     * @return 账号操作日志集合
     */
    @ApiOperation(value = "标签操作日志分页查询", notes = "标签操作日志分页数据")
    @GetMapping(value = "/log")
    public BasePageResponse<List<LogDetailVO>> lisOperateLogByPage(OperateLogQuery operateLogQuery) {
        return logService.listOperateLogs(operateLogQuery);
    }

    @ApiOperation(value = "素材管理-商品信息下拉", notes = "商品信息下拉")
    @GetMapping("/goodsByGoodsName")
    public ResponseResult goodsByGoodsName(@RequestParam String goodsName) {
        List<GoodsDTO> list = goodsService.searchGoodsByGoodsNameDrop(goodsName);
        return ResultGenerator.genSuccessResult(list.stream().map(g -> {
            SourceGoodsDropVO vo = new SourceGoodsDropVO();
            vo.setId(g.getId());
            vo.setGoodsImage(g.getGoodsImage());
            vo.setGoodsName(g.getGoodsName());
            vo.setGoodsPrice(g.getGoodsPrice());
            vo.setCategoryId(g.getCreatgroyFirst());
            vo.setCreatgroyName(g.getCreatgroyName());
            return vo;
        }).collect(Collectors.toList()));
    }

    /**
     * 将商品spu VO对象转换为DTO对象
     *
     * @param goods 商品spu VO
     * @return GoodsDTO 商品spu DTO
     */
    private GoodsDTO convertGoodsVo2Dto(GoodsVO goods) {
        GoodsDTO targetGoods = null;
        try {
            targetGoods = goods.clone(GoodsDTO.class, CloneDirection.FORWARD);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return targetGoods;
    }

    @ApiOperation(value = "添加库存-获取sku信息", notes = "添加库存-获取sku信息")
    @ApiImplicitParam(name = "id", value = "商品主键id")
    @GetMapping("/skuStockList")
    public ResponseResult<List<GoodsSkuStockVO>> skuStockList(@RequestParam Long id) {
        //获取物料id集合
        List<Long> supplySkuIds = goodsService.selectSkuIdsBySpuId(id);
        //库存信息
        List<CommodityMaterialStockDTO> materialStocks = getSupplyStockList(supplySkuIds, NumberConstant.NUMBER_ZERO);
        List<GoodsSkuStockDTO> list = goodsService.skuStockList(id);
        list.stream().forEach(dto -> {
            //物料库存赋值
            CommodityMaterialStockDTO jmCommodityMaterialStock = materialStocks.stream().filter(m -> dto.getMaterialSkuId().equals(m.getMaterialId())).findAny().orElse(null);
            if (jmCommodityMaterialStock != null) {
                dto.setMaterialStorage(jmCommodityMaterialStock.getAvailableStockNum());
            }
        });
        return ResultGenerator.genSuccessResult(dtos2Vos(goodsInventoryApi.goodsSkuInventoryList(list)));
    }

    @ApiOperation(value = "添加库存-获取sku信息(组合商品)", notes = "添加库存-获取sku信息(组合商品)")
    @ApiImplicitParam(name = "id", value = "商品主键id")
    @GetMapping("/skuStockListCombination")
    public ResponseResult skuStockListCombination(@RequestParam Long id) {
        //获取物料id集合
        GoodsMateriaDTO goodsMateria = goodsService.selectCombinationSkuIdsBySpuId(id);
        //获取返回的sku物料id
        List<Long> supplySkuIds = goodsMateria.getMateriaSkuIds();
        //库存信息
        List<CommodityMaterialStockDTO> materialStocks = getSupplyStockList(supplySkuIds, NumberConstant.NUMBER_ZERO);
        List<GoodsMateriaSpuDTO> goodsMateriaSpus = goodsMateria.getGoodsMateriaSpus();
        //用于计算sku物料库存
        List<CombGoodsMateriaStockDTO> combGoodsMateriaStocks = new ArrayList<>();
        //物料库存值
        goodsMateriaSpus.stream().forEach(dto -> {
            List<GoodsMateriaSkuDTO> skus = dto.getSkus();
            skus.stream().forEach(s -> {
                //物料库存赋值
                CommodityMaterialStockDTO jmCommodityMaterialStock = materialStocks.stream().filter(m -> s.getMateriaSkuId().equals(m.getMaterialId())).findAny().orElse(null);
                if (jmCommodityMaterialStock != null) {
                    s.setStockNum(jmCommodityMaterialStock.getAvailableStockNum());
                    //封装物料库存信息
                    CombGoodsMateriaStockDTO c = new CombGoodsMateriaStockDTO();
                    c.setComposeNum(s.getComposeNumber());
                    c.setSupplyStock(s.getStockNum());
                    combGoodsMateriaStocks.add(c);
                }
            });
        });
        //获取实时库存
        List<GoodsSkuStockDTO> list = goodsService.skuStockList(id);
        if (CollectionUtil.isNotEmpty(combGoodsMateriaStocks)) {
            packComposeStock(combGoodsMateriaStocks, list);
        }
        return ResultGenerator.genSuccessResult(new GoodsMateriaVO(goodsMateriaSpus, dtos2Vos(goodsInventoryApi.goodsSkuInventoryList(list))));
    }

    /**
     * 添加库存
     *
     * @param vo 商品sku库存值对象
     */
    @ApiOperation(value = "添加库存", notes = "商品添加库存")
    @PostMapping("/addInventory")
    public ResponseResult addInventory(@RequestBody SkuSupplyAddVO vo, @RequestHeader(RequestConstant.ADMIN_NAME) String username) {
        //判断商品sku库存
        ExceptionEnum.FAIL_GOODS_SKU_EXIST.doThrowIf(vo == null);
        //判断所有的sku提交时 都为0
        AtomicReference<String> msg = new AtomicReference<>();
        vo.getList().stream().allMatch(v->{
            if (v.getPreStorage() == 0 && v.getStockQuantity() == 0) {
                msg.set("所有sku的添加数量与预售数量不能同时为0");
                return true;
            }
            //20210111  针对组合商品的库存校验
            if(v.getStockQuantity()>v.getMaterialStorage()){
                msg.set("sku编码:"+v.getSkuId()+"库存不足");
                return true;
            }
            return false;
        });
        if(StrUtil.isNotEmpty(msg.get())){
            return ResultGenerator.genFailResult(msg.get());
        }
        //获取物料id集合
        List<Long> supplySkuIds = goodsService.selectSkuIdsBySpuId(vo.getId());
        //库存信息
        List<CommodityMaterialStockDTO> materialStocks = getSupplyStockList(supplySkuIds, NumberConstant.NUMBER_ONE);
        //创建供应链服务dto
        CommodityApplyDTO commodityApplyDTO = new CommodityApplyDTO();
        commodityApplyDTO.setCreateBy(username);
        //状态未分配
        commodityApplyDTO.setStatus(NumberConstant.NUMBER_ZERO.intValue());
        commodityApplyDTO.setPreStockTotalNum(NumberConstant.NUMBER_ZERO.intValue());
        commodityApplyDTO.setStockTotalNum(NumberConstant.NUMBER_ZERO.intValue());
        //判断库存值是否大于物料值
        vo.getList().stream().forEach(v -> {
            //累加处理添加/预售库存总量
            commodityApplyDTO.setPreStockTotalNum(commodityApplyDTO.getPreStockTotalNum() + v.getPreStorage());
            commodityApplyDTO.setStockTotalNum(commodityApplyDTO.getStockTotalNum() + v.getStockQuantity());
            //判断添加库存是否大于0
            if (v.getStockQuantity() > 0) {
                CommodityMaterialStockDTO jmCommodityMaterialStock = materialStocks.stream().filter(m -> v.getMaterialSkuId().equals(m.getMaterialId())).findAny().orElse(null);
                if (jmCommodityMaterialStock != null) {
                    //判断物料库存是否大于添加库存
                    SupplyServerEnum.FAIL_STOCK_NUM_BIG.doThrowIf(v.getStockQuantity() > jmCommodityMaterialStock.getAvailableStockNum());
                }
            }
        });
        //封装服务参数
        goodsService.encapsulationStock(commodityApplyDTO, vo);
//        SupplySkuStockDTO supplySkuStockDTO = new SupplySkuStockDTO();
//        supplySkuStockDTO.setStockApplyRequest(stockApplyRequest);
//        supplySkuStockDTO.setList(dtos);
        //库存的中库存信息在供应链审核后入库操作
//        inventoryService.saveInventory(supplySkuStockDTO);
        //调用供应链服务添加库存
        supplyStockService.addCommodityApply(commodityApplyDTO);
        return ResultGenerator.genSuccessResult();
    }

    /**
     * 清除库存
     *
     * @param id 商品sku主键id
     */
    @ApiOperation(value = "清除库存", notes = "商品清除库存")
    @ApiImplicitParam(name = "id", value = "商品sku主键id")
    @PostMapping("/clearInventory")
    public ResponseResult clearInventory(@RequestParam Long id, @RequestHeader(RequestConstant.ADMIN_NAME) String username) {
        ClearSkuMaterialDTO clearSkuSpply = goodsService.clearInventory(id);
        //库存服务清除库存
        clearSkuSpply.setUserName(username);
        goodsInventoryApi.clearInventory(clearSkuSpply);
        return ResultGenerator.genSuccessResult();
    }

    /**
     * 订单-预售转实际列表
     *
     * @param spuId 商品spu主键id
     */
    @ApiOperation(value = "订单-预售转实际列表", notes = "订单-预售转实际列表")
    @ApiImplicitParam(name = "spuId", value = "商品spu主键id")
    @PostMapping("/pre2RealSkuList")
    public ResponseResult pre2RealSkuList(@RequestParam Long spuId) {
        //封装商品sku信息
        GoodsSkuStockIdDTO goodsSkuStockIdDTO = goodsService.getGoodsSkuAndIdsBySpuId(spuId);
        List<GoodsStockWareDTO> list = goodsInventoryApi.getGoodsStockWare4OrderBySpuId(goodsSkuStockIdDTO);
        return ResultGenerator.genSuccessResult(list);
    }

    /**
     * 订单-预售转实际 (只记录日志 业务操作放在订单服务)
     *
     * @param goodsStockWares 商品sku库存信息
     */
    @ApiOperation(value = "订单-预售转实际", notes = "订单-预售转实际")
    @ApiImplicitParam(name = "goodsStockWares", value = "商品sku库存信息")
    @PostMapping("/pre2RealStock")
    public ResponseResult pre2RealStock(@RequestBody GoodsPre2RealStockVO goodsStockWares,
                                        @RequestHeader(RequestConstant.ADMIN_NAME) String userName) {
//        ExceptionEnum.FAIL_GOODS_SKU_EXIST.doThrowIf(CollectionUtil.isEmpty(goodsStockWares.getGoodsStockWares()));
//        //封装库存调用dto
//        WareAndSkuIdsDTO wareAndGoodsSkus = packWareGoods(goodsStockWares.getGoodsStockWares());
//        if (CollectionUtil.isNotEmpty(wareAndGoodsSkus.getSkuIds())) {
//            //库存服务修改库存
//            goodsInventoryApi.pre2RealWareStock4Order(wareAndGoodsSkus);
//        }
        //记录业务日志  业务操作放在订单服务
        goodsService.addPre2RealStockLog(new OrderStockLog(goodsStockWares.getSpuId(), goodsStockWares.getSpuName(), goodsStockWares.getStockNum(), userName));
        return ResultGenerator.genSuccessResult(true);
    }

    @ApiOperation(value = "查询分页", notes = "获取预售转真实日志分页数据")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "当前页码"),
            @ApiImplicitParam(name = "size", value = "分页大小"),
    })
    @GetMapping("/pre2RealLoglist")
    public BasePageResponse list(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size,
            OrderStockLog log) {
        IPage<OrderStockLog> pageInfo = goodsService.stockLogPage(new Page<>(page, size), log);
        return ResultGenerator.genSuccessResultPage(pageInfo.getRecords(), pageInfo.getTotal());
    }


    @ApiOperation(value = "商品管理-所有上架商品列表分页查询", notes = "商品管理-所有上架商品列表分页查询")
    @GetMapping("/releaseList")
    public BasePageResponse<List<GoodsShowVO>> releaseListGoodsByPage(GoodsQuery goodsQuery) {
        List<GoodsShowVO> goodsShows = convertGoodsShowDtoList2VoList(goodsService.releaseListGoods(goodsQuery));
        return ResultGenerator.genSuccessResultPage(
                goodsShows.stream()
                        .skip(goodsQuery.getPageSize() * (goodsQuery.getPageNum() - NumberConstant.NUMBER_ONE.intValue()))
                        .limit(goodsQuery.getPageSize()).collect(Collectors.toList())
                , Long.valueOf(goodsShows.size()));
    }


    /**
     * 将商品spu DTO对象转换为VO对象
     *
     * @param goods 商品spu DTO
     * @return GoodsVO 商品spu VO
     */
    private GoodsVO convertGoodsDto2Vo(GoodsDTO goods) {
        GoodsVO targetGoods = null;
        try {
            targetGoods = goods.clone(GoodsVO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return targetGoods;
    }

    /**
     * 将商品供应商DTO对象集合转换为VO对象集合
     *
     * @param suppliers 商品供应商DTO集合
     * @return List<SupplierVO> 商品供应商VO对象集合
     */
    private List<SupplierVO> convertSupplierDtoList2VoList(List<SupplierDTO> suppliers) {
        List<SupplierVO> targetSuppliers = null;
        try {
            targetSuppliers = ObjectUtils.convertList(suppliers, SupplierVO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return targetSuppliers;
    }

    /**
     * 将DTO对象集合转换为VO对象集合
     *
     * @param goodsShows DTO集合
     * @return List<GoodsShowVO> VO对象集合
     */
    private List<GoodsShowVO> convertGoodsShowDtoList2VoList(List<GoodsShowDTO> goodsShows) {
        List<GoodsShowVO> targetGoodsShows = null;
        try {
            targetGoodsShows = ObjectUtils.convertList(goodsShows, GoodsShowVO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return targetGoodsShows;
    }

    private GoodsSkuStockDTO skuVo2Dto(GoodsSkuStockVO vo) {
        GoodsSkuStockDTO dto = null;
        try {
            dto = vo.clone(GoodsSkuStockDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return dto;
    }

    /**
     * 库存服务的dto->vo
     *
     * @param list 商品DO集合
     * @return List<GoodsSkuStockVO> 商品库存信息对象
     */
    private List<GoodsSkuStockVO> dtos2Vos(List<GoodsSkuStockDTO> list) {
        List<GoodsSkuStockVO> vos = list.stream().map(dto -> {
            GoodsSkuStockVO vo = null;
            try {
                vo = dto.clone(GoodsSkuStockVO.class);
            } catch (Exception e) {
                ExceptionEnum.FAIL_CHANGE.newException();
            }
            return vo;
        }).collect(Collectors.toList());
        return vos;
    }

    /**
     * 获取供应链库存信息
     *
     * @param supplySkuIds sku物料id集合
     * @return
     */
    private List<CommodityMaterialStockDTO> getSupplyStockList(List<Long> supplySkuIds, Long type) {
        ResponseResult<List<CommodityMaterialStockDTO>> stockResult = supplyStockService.getMaterialStockByMaterialIds(supplySkuIds);
        //库存服务是否成功
        SupplyServerEnum.FAIL_SUPPLY_STOCK_RESULT.doThrowIf(ResultEnum.FAIL.getCode() == stockResult.getCode());
        List<CommodityMaterialStockDTO> materialStocks = stockResult.getData();
        //物料可用库存是否为空 保存库存时需要返回物料库存值
//        if (NumberConstant.NUMBER_ONE.equals(type)) {
//            SupplyServerEnum.FAIL_SUPPLY_STOCK_NULL.doThrowIf(materialStocks.size() == NumberConstant.NUMBER_ZERO.intValue());
//        }
        return materialStocks;
    }

    /**
     * 封装库存服务 sku库存信息dto
     *
     * @param goodsStockWares
     * @param
     */
    private WareAndSkuIdsDTO packWareGoods(List<GoodsStockWareDTO> goodsStockWares) {
        List<WareAndGoodsSkuDTO> wareAndGoodsSkus = new ArrayList<>();
        //skuid集合
        List<Long> skuIds = new ArrayList<>();
        //仓库id集合
        List<Long> wareIds = new ArrayList<>();
        //sku库存集合
        Map<Long, Integer> map = new HashMap<>();
        goodsStockWares.stream().forEach(sku -> {
            //取仓库sku信息
            List<GoodsSkuStockWareDTO> skuStockWareDTOS = sku.getSkuStockWareDTOS();
            skuStockWareDTOS.stream().forEach(sto -> {
                if (sto.getStockNum() != null && sto.getStockNum() > NumberConstant.NUMBER_ZERO.intValue()) {
                    WareAndGoodsSkuDTO wareAndGoodsSkuDTO = new WareAndGoodsSkuDTO();
                    wareAndGoodsSkuDTO.setWareId(sku.getWareId());
                    wareAndGoodsSkuDTO.setSkuId(sto.getSkuId());
                    wareAndGoodsSkuDTO.setStockNum(sto.getAddStockNum());
                    wareAndGoodsSkuDTO.setSkuCode(sto.getSkuCode());
                    skuIds.add(sto.getSkuId());
                    wareIds.add(sku.getWareId());
                    wareAndGoodsSkus.add(wareAndGoodsSkuDTO);
                    //封装sku库存集合
                    packSkuMap(map, sto);
                }
            });
        });
        return new WareAndSkuIdsDTO(skuIds, wareIds, wareAndGoodsSkus, map);
    }

    /**
     * 封装sku库存map
     *
     * @param goodsSkuStockWare
     * @return
     */
    private void packSkuMap(Map<Long, Integer> map, GoodsSkuStockWareDTO goodsSkuStockWare) {
        //如果map中存在该sku累加
        if (map.containsKey(goodsSkuStockWare.getSkuId())) {
            map.put(goodsSkuStockWare.getSkuId(), map.get(goodsSkuStockWare.getSkuId()) + goodsSkuStockWare.getStockNum());
        } else {
            map.put(goodsSkuStockWare.getSkuId(), goodsSkuStockWare.getStockNum());
        }
    }

    /**
     * 组合商品sku的物料库存计算
     *
     * @param combGoodsMateriaStocks 物料库存和组合商品的对应关系
     * @param list                   商品sku信息
     */
    private void packComposeStock(List<CombGoodsMateriaStockDTO> combGoodsMateriaStocks, List<GoodsSkuStockDTO> list) {
        combGoodsMateriaStocks = combGoodsMateriaStocks.stream().filter(com -> com.getComposeNum() != 0).collect(Collectors.toList());
        //获取组合的最小值
        Optional<CombGoodsMateriaStockDTO> stock = combGoodsMateriaStocks.stream().min(Comparator.comparing(com -> com.getSupplyStock() / com.getComposeNum()));
        //封装sku信息 组合商品sku只有一个 直接foreach赋值
        list.stream().forEach(g -> {
            g.setMaterialStorage(stock.get().getSupplyStock() / stock.get().getComposeNum());
        });
    }

}
